<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>学知鸟</title>
		<link rel="shortcut icon" href="../../share/img/logo.png">
		<link rel="stylesheet" href="../../share/css/main.css">
		<script src="../../share/js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script>
		<style>
			.box1 {
				width: 80px;
				height: 80px;
				background-color: red;
				display: flex;
				align-items: center;
				justify-content: center;
			}

			.box2 {
				width: 50px;
				height: 50px;
				background-color: blue;
			}
		</style>
	</head>
	<body class="p-10">
		<h1>异步</h1>
		<div class="row">
			<div class="col-1">
				<section>
					<h3>定时器</h3>
					<button id="btn1"></button>
					<button id="btn4">定点任务</button>
					<button id="btn5">定期任务</button>
					<br />
					<span id="info1"></span>
				</section>
				<section>
					<h3>异步协作</h3>
					<button id="btn2">串行执行</button>
					<button id="btn3">并行执行</button>
				</section>
				<section>
					<h3>setTimeout(0)</h3>
					<div class="row">
						<div class="col-1">
							<div class="mb-10">
								<label>普通点击</label>
							</div>
							<div class="box1" id="box1">
								<div class="box2" id="box2">
								</div>
							</div>
						</div>
						<div class="col-1">
							<div class="mb-10">
								<label>延时点击</label>
							</div>
							<div class="box1" id="box3">
								<div class="box2" id="box4">
								</div>
							</div>
						</div>
						<div class="col-1">
							<div class="mb-10">
								<label>普通按键处理</label>
							</div>
							<input id="ipt1" />
						</div>
						<div class="col-1">
							<div class="mb-10">
								<label>延时按键处理</label>
							</div>
							<input id="ipt2" />
						</div>
					</div>
				</section>
				<section>
					<h3>Promise</h3>
					<button id="btn6">订票</button>
					<button id="btn7">微任务</button>
				</section>
			</div>
			<div class="col-1">
				<section>
					<h3>日志</h3>
					<button onclick="util.clearLog()">清空日志</button>
					<ul id="log" class="d-list mt-10">
					</ul>
				</section>
			</div>
		</div>

		<script type="text/javascript">
			var util = {
				logId: "#log",
				pad0(n) {
					return n > 9 ? n : "0" + n;
				},
				getTime() {
					let now = new Date();
					return this.pad0(now.getHours()) + ":" + this.pad0(now.getMinutes()) + ":" + this.pad0(now.getSeconds());
				},
				sleep(ms) {
					let from = new Date();
					while (new Date() - from < ms);
				},
				clearLog() {
					$(this.logId).empty();
					return this;
				},
				appendLog(text) {
					text = this.getTime() + " " + text;
					$(this.logId).append(`<li>${text}</li>`);
					return this;
				}
			};

			// 定时器 -----------------------------------
			var timer1 = {
				id: 0,
				infoId: "#info1",
				btnId: "#btn1",
				init: function() {
					$(this.btnId).click(this.toggle.bind(this)).text("开始定时器");
				},
				start: function() {
					if (this.running()) return;
					this.id = setInterval(this.showInfo.bind(this), 1000);
					this.showInfo();
				},
				stop: function() {
					if (!this.running()) return;
					clearInterval(this.id);
					this.id = 0;
				},
				toggle: function() {
					this.running() ? this.stop() : this.start();
					$(this.btnId).text(this.running() ? "停止定时器" : "开始定时器");
				},
				running: function() {
					return this.id > 0;
				},
				showInfo: function() {
					$(this.infoId).text(util.getTime());
				}
			};
			timer1.init();

			// setTimeout -----------------------------------
			var timer2 = {
				btnId: "#btn4",
				init() {
					$(this.btnId).click(function() {
						let n1 = 3,
							n2 = 1;
						setTimeout(function() {
							util.appendLog("开始睡觉 ...");
						}, n2);
						util.clearLog().appendLog(`开始吃饭, 需要${n1}秒, ${n2}秒后要睡觉 ... `);
						util.sleep(n1 * 1000);
						util.appendLog("吃饭完成!");
					});
				}
			};
			timer2.init();

			// setInterval -----------------------------------
			var timer3 = {
				id: 0,
				btnId: "#btn5",
				init() {
					$(this.btnId).click(this.toggle.bind(this));
				},
				toggle() {
					if (this.id == 0) {
						let n1 = 3,
							n2 = 1;
						this.id = setInterval(function() {
							util.appendLog("心跳");
						}, n2 * 1000);
						util.clearLog().appendLog(`开始吃饭, 需要${n1}秒 ... `);
						util.sleep(n1 * 1000);
						util.appendLog("吃饭完成!");

					} else {
						clearInterval(this.id);
						this.id = 0;
						util.appendLog("停止!");
					}
				},

			};
			timer3.init();

			// 延时点击 -----------------------------------
			var timer3 = {
				box1: "#box1",
				box2: "#box2",
				box3: "#box3",
				box4: "#box4",
				init() {
					$(this.box1).click(function() {
						util.appendLog("点击外层元素");
					});
					$(this.box2).click(function() {
						util.appendLog("点击内层元素");
					});
					$(this.box3).click(function() {
						util.appendLog("点击外层元素");
					});
					$(this.box4).click(function() {
						setTimeout(function() {
							util.appendLog("点击内层元素");
						}, 0);
					});
				}
			};
			timer3.init();

			// 延时按键 -----------------------------------
			var timer4 = {
				ipt1: "#ipt1",
				ipt2: "#ipt2",
				init() {
					$(this.ipt1).keypress(function() {
						$(this).val($(this).val().toUpperCase());
					});
					$(this.ipt2).keypress(function() {
						let that = this;
						setTimeout(function() {
							$(that).val($(that).val().toUpperCase());
						}, 0);
					});
				}
			};
			timer4.init();

			// 异步协作 -----------------------------------
			var taskManager = {
				tasks: [],
				init() {
					$("#btn2").click(taskManager.start1.bind(this));
					$("#btn3").click(taskManager.start2.bind(this));
				},
				start1() {
					this.reset();
					util.clearLog().appendLog("开始串行执行任务 ...");
					this.run1();
				},
				start2() {
					this.reset();
					util.clearLog().appendLog("开始并行执行任务 ...");
					this.run2();
				},
				reset() {
					// 应为函数数组，为简便仅保存参数
					this.tasks = ["起床", "洗漱", "吃饭", "娱乐", "睡觉"];
				},
				run1() {
					if (this.tasks.length < 1) {
						util.appendLog("完成任务列表!");
						return;
					}
					let fn = this.tasks.shift(); // 应为函数，实为参数
					util.appendLog("正在执行任务 " + fn + " ...");
					// fn(); 应为调用函数，实仅输出信息
					setTimeout(this.run1.bind(this), 1000);
				},
				run2() {
					let that = this;
					this.tasks.forEach(function(item) {
						util.appendLog("正在执行任务 " + item + " ...");
					})
				},
				run3() {},
			};
			taskManager.init();

			// Promise -----------------------------------
			var task1 = {
				btnId: "#btn6",
				init() {
					$(this.btnId).click(this.run.bind(this));
				},
				book() {
					return new Promise(function(resolve, reject) {
						util.appendLog("正在订票 ...");
						util.sleep(500);
						let id = Math.round(Math.random() * 10) + 1;
						if (id < 6) {
							resolve(id);
						} else {
							reject(new Error("订购失败，票源不足!"));
						}
					});
				},
				run() {
					util.clearLog();
					/* this.book().then(function(value) {
						util.appendLog("订购成功，票号:" + value);
						return value;
					}).then(function(value) {
						util.appendLog("欢迎" + value + "号乘客乘车!");
					}).catch(function(err) {
						util.appendLog(err.message);
					}).finally(); */
					let p1 = this.book();
					let p2 = p1.then(function(value) {
						util.appendLog("订购成功，票号:" + value);
						return value;
					});
					let p3 = p2.then(function(value) {
						util.appendLog("欢迎" + value + "号乘客乘车!");
					});
					let p4 = p3.catch(function(err) {
						util.appendLog(err.message);
					});
					p4.finally(function() {
						util.appendLog("订票结束");
					});
					console.log(p1, p2, p3);
					console.log(p1 == p2, p2 == p3);
				}
			};
			task1.init();

			// 微任务 -----------------------------------
			var task2 = {
				btnId: "#btn7",
				init() {
					$(this.btnId).click(this.run.bind(this));
				},
				run() {
					util.clearLog();
					setTimeout(function() {
						util.appendLog("setTimeout 异步任务")
					}, 0);
					new Promise(function(resolve, reject) {
						resolve();
					}).then(function() {
						util.appendLog("Promise 微任务")
					});
					util.appendLog("同步任务");
				}
			};
			task2.init();
		</script>
	</body>
</html>
